package com.shelpe.services.sinbad.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.shelpe.services.sinbad.controller.LogDto.LogNoteable;
import com.shelpe.services.sinbad.dto.common.PagableList;
import com.shelpe.services.sinbad.entity.jpa.BehaviorTag;
import com.shelpe.services.sinbad.entity.jpa.BuyerBehaviorAnalysis;
import com.shelpe.services.sinbad.entity.jpa.ExpertAnalysis;
import com.shelpe.services.sinbad.entity.jpa.ExpertDistribution;
import com.shelpe.services.sinbad.entity.jpa.RptKeywordAnalysis;
import com.shelpe.services.sinbad.entity.jpa.User;
import com.shelpe.services.sinbad.repository.jpa.BuyerBehaviorAnalysisRepository;
import com.shelpe.services.sinbad.repository.jpa.ExpertAnalysisRepository;
import com.shelpe.services.sinbad.repository.jpa.ExpertDistributionRepository;
import com.shelpe.services.sinbad.repository.jpa.RptKeywordAnalysisRepository;
import com.shelpe.services.sinbad.repository.jpa.UserRepository;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/sinbadservice")
@Slf4j
@Api(value = "分析相关的API", consumes = "application/json")
public class AnalysisController {
	@Autowired
	private BuyerBehaviorAnalysisRepository buyerBehaviorAnalysisRepository;
	@Autowired
	private RptKeywordAnalysisRepository rptKeywordAnalysisRepository;
	@Autowired
	private ExpertAnalysisRepository expertAnalysisRepository;
	@Autowired
	private ExpertDistributionRepository expertDistributionRepository;
	@Autowired
	private UserRepository usersRepository;

	@ApiOperation(value = "直通车诊断之查看所有")
	@RequestMapping(method = RequestMethod.GET, path = "/users/{user_id}/experts")
	@ResponseBody
	public ExpertAnalysisResponse findExpertDetial(@PathVariable("user_id") long userID) {
		ExpertAnalysisResponse dto = new ExpertAnalysisResponse();
		this.findExpert(userID, dto);
		return dto;
	}

	@ApiOperation(value = "直通车诊断诊断删除")
	@RequestMapping(method = RequestMethod.DELETE, path = "/expertDistribution")
	@ResponseBody
	public Response deleteExpertDistribution(){
		List<ExpertDistribution> needExperts = (List<ExpertDistribution>) this.expertDistributionRepository.findAll();
		if(needExperts != null && needExperts.size() > 0){
			this.expertDistributionRepository.delete(needExperts);
		}
		Response res = new Response();
		res.setStatus(true);
		return res;
	}
	
	private void findExpert(long userID, ExpertAnalysisResponse dto) {
		dto.setExpertData(new ArrayList<ExpertAnalysisDto>());
		List<ExpertAnalysis> experts = (List<ExpertAnalysis>) this.expertAnalysisRepository.findAll();
		Calendar cal = Calendar.getInstance();
		if (experts != null && experts.size() > 0) {
			// 判断今天是否一号，若是，则刷新申请状态
			List<ExpertDistribution> needExperts = this.expertDistributionRepository.findByUserID(userID);
			if (needExperts != null && needExperts.size() > 0) {
				if (cal.get(Calendar.DAY_OF_MONTH) == 1) {
					this.expertDistributionRepository.delete(needExperts);
				} else {
					dto.setApplyStatus(true);
				}
			}

			for (ExpertAnalysis expert : experts) {
				ExpertDistribution distribution = this.expertDistributionRepository.findByUserIDAndExpertID(userID,
						expert.getExpertID());
				ExpertAnalysisDto voDto = new ExpertAnalysisDto();
				if (distribution != null) {
					voDto.setApply(true);
				}
				BeanUtils.copyProperties(expert, voDto);
				dto.getExpertData().add(voDto);
			}
		}
	}

	@ApiOperation(value = "直通车诊断之更新申请状态")
	@RequestMapping(method = RequestMethod.PUT, path = "/users/{user_id}/experts/{expert_id}")
	@ResponseBody
	public Response updateExpert(@PathVariable("user_id") long userID, @PathVariable("expert_id") long expertID,
			@RequestBody ExpertAnalysisDto dto) {
		Response res = new Response();
		User user = this.usersRepository.findOne(userID);
		Assert.notNull(user, "user_not_exist");
		ExpertAnalysis expert = this.expertAnalysisRepository.findByExpertID(expertID);
		ExpertDistribution expertDistribution = new ExpertDistribution();
		BeanUtils.copyProperties(expert, expertDistribution);
		expertDistribution.setExpertName(expert.getName());
		expertDistribution.setUserID(userID);
		expertDistribution.setNick(user.getNick());
		expertDistribution.setIsApply(1);
		expertDistribution.setUpdatedTime(new Date());
		this.expertDistributionRepository.save(expertDistribution);
		res.setStatus(true);

		return res;
	}

	@Data
	public static class Response {
		private boolean status;
	}

	@Data
	public static class ExpertAnalysisDto {
		@JsonProperty("expert_id")
		private long expertID;
		private String content;// 专家简介
		@JsonProperty("is_apply")
		private boolean apply;// 是否申请 0:未申请 1:已申请
		private int star;
		private String img;
		private String name;
	}

	@Data
	public static class ExpertAnalysisResponse {
		@JsonProperty("expert_data")
		private List<ExpertAnalysisDto> expertData;
		@JsonProperty("is_apply")
		private boolean applyStatus;
	}

	@ApiOperation(value = "自然搜索词分析")
	@RequestMapping(method = RequestMethod.GET, path = "/users/{user_id}/analysis_reports/natural_search")
	@ResponseBody
	public Page<LogDto<LogDto.LogNoteable>> findNaturalSearchAnalysis(@PathVariable("user_id") long userID,
			@RequestParam(name = "page_num", defaultValue = "0") int page,
			@RequestParam(name = "page_size", defaultValue = "50") int size,
			@RequestParam(name = "sort", defaultValue = "", required = false) String sort,
			@RequestParam(name = "direct", defaultValue = "desc") String direct,
			@RequestParam(name = "search_keyword", defaultValue = "", required = false) String keyword,
			@RequestParam(name = "device", defaultValue = "mobile", required = false) String device) {
		PageRequest pr = new PageRequest(page, size);
		if (StringUtils.isNotBlank(sort)) {
			pr = PagableList.builder(page, size).direction(direct).sort(sort, LogDto.class).build();
		}

		Date today = DateUtils.truncate(new Date(), Calendar.DATE);
		Page<LogDto<LogDto.LogNoteable>> dtos = null;

		Page<RptKeywordAnalysis> rptkws = null;
		if (device.equals("mobile")) {
			if (StringUtils.isNotBlank(keyword)) {
				rptkws = this.rptKeywordAnalysisRepository
						.findByUserIDAndKeywordstrLikeAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(userID,
								"%" + keyword + "%", 45, DateUtils.addDays(today, -7), pr);
			} else {
				rptkws = this.rptKeywordAnalysisRepository.findByUserIDAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(
						userID, 45, DateUtils.addDays(today, -7), pr);
			}
		} else {
			if (StringUtils.isNotBlank(keyword)) {
				rptkws = this.rptKeywordAnalysisRepository
						.findByUserIDAndKeywordstrLikeAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(userID,
								"%" + keyword + "%", 12, DateUtils.addDays(today, -7), pr);
			} else {
				rptkws = this.rptKeywordAnalysisRepository.findByUserIDAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(
						userID, 12, DateUtils.addDays(today, -7), pr);
			}
		}
		List<LogDto<LogDto.LogNoteable>> list = new ArrayList<LogDto<LogDto.LogNoteable>>();
		for (RptKeywordAnalysis rptkw : rptkws) {
			LogDto<LogNoteable> dto = new LogDto<LogNoteable>();
			BeanUtils.copyProperties(rptkw, dto);
			dto.setKeyword(rptkw.getKeywordstr());
			list.add(dto);
		}
		dtos = new PageImpl<LogDto<LogDto.LogNoteable>>(list, pr, rptkws.getTotalElements());

		log.debug("finish findNaturalSearchAnalysis:{}", dtos);
		return dtos;
	}

	@ApiOperation(value = "直通车用户访问分析")
	@RequestMapping(method = RequestMethod.GET, path = "/users/{user_id}/analysis_reports/direct_train")
	@ResponseBody
	public Page<LogDto<LogDto.LogNoteable>> findDirectTrainUserAnalysis(@PathVariable("user_id") long userID,
			@RequestParam(name = "page_num", defaultValue = "0") int page,
			@RequestParam(name = "page_size", defaultValue = "50") int size,
			@RequestParam(name = "device", defaultValue = "mobile", required = false) String device) {
		PageRequest pr = new PageRequest(page, size);
		Date today = DateUtils.truncate(new Date(), Calendar.DATE);
		Page<LogDto<LogDto.LogNoteable>> dtos = null;
		int deepIndex = 1;
		int middleIndex = 1;
		int lightIndex = 1;

		Page<BuyerBehaviorAnalysis> buyers = null;
		if (device.equals("mobile")) {
			buyers = this.buyerBehaviorAnalysisRepository.findByUserIDAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(
					userID, 45, DateUtils.addDays(today, -7), pr);
		} else {
			buyers = this.buyerBehaviorAnalysisRepository.findByUserIDAndSourceAndCreateTimeAfterOrderByCreateTimeDesc(
					userID, 12, DateUtils.addDays(today, -7), pr);
		}
		List<LogDto<LogDto.LogNoteable>> list = new ArrayList<LogDto<LogDto.LogNoteable>>();
		for (BuyerBehaviorAnalysis buyer : buyers) {
			LogDto<LogNoteable> dto = new LogDto<LogNoteable>();
			List<BehaviorTag> tags = new ArrayList<BehaviorTag>();
			dto.from(buyer, tags);
			dto.from(tags);
			dto.setKeyword(buyer.getKeywordstr());
			if (Arrays.asList(dto.getBehaviorNames()).contains("buy")) {
				dto.setVisitDepth((int) (3 + Math.random() * 10));
				dto.setNick("深度用户aa" + deepIndex);
				deepIndex++;
			} else if (Arrays.asList(dto.getBehaviorNames()).contains("fav")
					|| Arrays.asList(dto.getBehaviorNames()).contains("cart")) {
				if (Arrays.asList(dto.getBehaviorNames()).contains("cart")) {
					dto.setVisitDepth((int) (2 + Math.random() * 7));
				} else {
					dto.setVisitDepth((int) (2 + Math.random() * 4));
				}
				dto.setNick("中度用户aa" + middleIndex);
				middleIndex++;
			} else {
				dto.setVisitDepth((int) (1 + Math.random() * 3));
				dto.setNick("浅度用户aa" + lightIndex);
				lightIndex++;
			}

			list.add(dto);
		}
		dtos = new PageImpl<LogDto<LogDto.LogNoteable>>(list, pr, buyers.getTotalElements());

		log.debug("finish findDirectTrainUserAnalysis:{}", dtos);
		return dtos;

	}
}
